package com.example.aspect.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * @author jimao.zou
 * @date 9/28/2018 2:32 PM
 * @description: TODO
 */
@Slf4j
@Aspect
@Component
public class LoggingAspect {
    public static final  String DOT=".";
    public static final  String TYPE_OUTPUT="<<TYPE>>:[{}],<<OUTPUT>>:[{}]";
    public static final  String TYPE_ARGS="<<TYPE>>:[{}],<<ARGS>>:[{}]";
    public static final  String TYPE="<<TYPE>>:[{}]";
    public static final  String NULL="NULL";

    @Pointcut("execution(* com.example.aspect.controller.*.*(..))")
    public void controllerAspect(){

    }

    @Before("controllerAspect()")
    public void logBeforeContollerMethodAspect(JoinPoint joinPoint){
        Object[] args=joinPoint.getArgs();
        if(args==null||args.length==0){
            log.info(TYPE,joinPoint.getSignature().toLongString());
            return;
        }
        StringBuilder builder=new StringBuilder();
            for(Object o : args){
                if(o != null){
                    builder.append("{ ").append(o.toString()).append(" }");
                }else{
                    builder.append("{ ").append(NULL).append(" }");
                }
            }
        log.info(TYPE_ARGS,getSimpleSignature(joinPoint),builder.toString());
    }

    @AfterReturning(value = "controllerAspect()",returning = "rvt")
    public Object logAfterControllerMethodAspect(JoinPoint joinPoint,Object rvt){
        if(log.isInfoEnabled()){
            if(rvt instanceof Optional){
                if(((Optional) rvt).isPresent()){
                    log.info(TYPE_OUTPUT,getSimpleSignature(joinPoint),((Optional) rvt).get());
                }else{
                    log.info(TYPE_OUTPUT,getSimpleSignature(joinPoint), NULL);
                }
            }else {
                log.info(TYPE_OUTPUT, getSimpleSignature(joinPoint), rvt);
            }
        }
        return rvt;
    }

    private String getSimpleSignature(JoinPoint joinPoint){
        return getSimpleName(joinPoint) + DOT + getMethodName(joinPoint);
    }

    private String getSimpleName(JoinPoint joinPoint){
        if(joinPoint != null){
            return joinPoint.getSignature().getDeclaringType().getSimpleName();
        }
        return NULL;
    }

    private String getMethodName(JoinPoint joinPoint){
        if(joinPoint != null){
            return joinPoint.getSignature().getName();
        }
        return NULL;
    }
}
